﻿#define _CRT_SECURE_NO_WARNINGS 1
//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	char ch = 'w';
//	char* pc = &ch;
//	printf("%d\n", sizeof(pa));
//	printf("%d\n", sizeof(pc));
//	return 0;
//}

//int main()
//{
//	int a = 0x11223344;
//	//int* pa = &a;
//	//*pa = 0;
//	char* pa = &a;//int*
//	*pa = 0;
//
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	int*pa = &a;
//	char* pc = &a;
//
//	printf("%p\n", pa);
//	printf("%p\n", pc);
//
//	printf("%p\n", pa+1);
//	printf("%p\n", pc+1);
//
//	return 0;
//}


//int main()
//{
//	int arr[10] = { 0 };
//
//	//如果希望按照一个整型的形式访问
//	//int* p = arr;
//	//int i = 0;
//	//for (i = 0; i < 10; i++)
//	//{
//	//	*p = 0x11223344;
//	//	p++;
//	//}
//	//假设你希望，你访问这个40个字节的时候，是以字节为单位访问
//	//char* p = (char*)arr;//int*
//	//int i = 0;
//	//for (i = 0; i < 40; i++)
//	//{
//	//	*p = 'x';
//	//	p++;
//	//}
//
//	return 0;
//}


//int main()
//{
//	int* p;
//	
//	*p = 20;
//
//	return 0;
//}
//


//int main()
//{
//	int arr[5] = { 1,2,3,4,5 };
//	int i = 0;
//
//	int* p = arr;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *p);
//		p++;
//	}
//
//	return 0;
//}


//int* test()
//{
//	int a = 10;
//	printf("%d\n", a);
//	return &a;
//}
//int main()
//{
//	int*p = test();
//	*p = 100;
//
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	int* p = &a;
//
//	int* q = NULL;
//
//	if (q != NULL)
//	{
//		//...
//	}
//
//	p = NULL;
//
//	return 0;
//}
//



//int main()
//{
//	int arr[10] = { 0 };
//
//	printf("%d\n", &arr[0] - &arr[9]);
//
//	return 0;
//}

//
//my_strlen
//1. 计数器的方法
//2. 递归
//3. 指针-指针
//

//int my_strlen(char* str)
//{
//	char* start = str;
//	while (*str)
//	{
//		str++;
//	}
//	return str - start;
//}
//
//int main()
//{
//	char arr[] = "abcdef";
//	int len = my_strlen(arr);
//	printf("%d\n", len);
//
//	return 0;
//}
//
// 
// 不管这个代码
//#include <stdio.h> 
//char* a; main(int t, int _, char* a) {
//	return!0 < t ? t < 3 ? main(-79, -13, a + main(-87, 1 - _,
//		main(-86, 0, a + 1) + a)) : 1, t < _ ? main(t + 1, _, a) : 3, main(-94, -27 + t, a) && t == 2 ? _ < 13 ?
//		main(2, _ + 1, "%s %d %d\n") : 9 : 16 : t < 0 ? t < -72 ? main(_, t,
//			"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
//		: t < -50 ? _ == *a ? putchar(31[a]) : main(-65, _, a + 1) : main((*a == '/') + t, _, a + 1)
//		: 0 < t ? main(2, 2, "%s") : *a == '/' || main(0, main(-61, *a,
//			"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"), a + 1);
//}
//


//
//数组名是数组首元素的地址
//但是有2个例外：
//sizeof(数组名)，数组名表示整个数组，计算的是整个数组的大小
//&数组名，数组名表示整个数组，取出的是整个数组的地址
//


//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	//              0 1 2 3 4 5 6 7 8 9
//	int* p = arr;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//	//printf("%p\n", arr);//
//	//printf("%p\n", &arr[0]);
//	//printf("%d\n", sizeof(arr));
//	return 0;
//}
//
//int main()
//{
//	int arr[10] = { 0 };
//	printf("%p\n", arr);
//	printf("%p\n", arr+1);
//
//	printf("%p\n", &arr[0]);
//	printf("%p\n", &arr[0]+1);
//
//	printf("%p\n", &arr);
//	printf("%p\n", &arr+1);
//
//
//	return 0;
//}

//
//int main()
//{
//	int a = 10;
//	int* pa = &a;//pa是指针变量（一级指针）
//	int** ppa = &pa;//ppa是一个二级指针
//	
//	int*** pppa = &ppa;//pppa就是三级指针
//
//	return 0;
//}
//

//指针数组 - 存放指针的数组
//整型数组

//int main()
//{
//	//int arr[5];//指针数组 - 存放整型的数组
//	//char ch[6];//字符数组 -存放字符的数组
//
//	int a = 10;
//	int b = 11;
//	int c = 12;
//	int d = 13;
//	int e = 14;
//	int* arr2[5] = {&a, &b, &c, &d, &e};//指针数组
//
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		printf("%d ", *(arr2[i]));
//	}
//	return 0;
//}

//int main()
//{
//	int data1[] = { 1,2,3,4,5 };
//	int data2[] = { 2,3,4,5,6 };
//	int data3[] = { 3,4,5,6,7 };
//
//	//arr就是一个指针数组
//	int* arr[3] = { data1 ,data2, data3 };
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 5; j++)
//		{
//			printf("%d ", arr[i][j]);
//		}
//		printf("\n");
//	}
//
//	return 0;
//}



//作业自补
//求两个数二进制中不同位的个数
//编程实现：两个int（32位）整数m和n的二进制表达中，有多少个位(bit)不同？ 
/*
思路：
1. 先将m和n进行按位异或，此时m和n相同的二进制比特位清零，不同的二进制比特位为1
2. 统计异或完成后结果的二进制比特位中有多少个1即可
*/
//#include <stdio.h>
//int calc_diff_bit(int m, int n)
//{
//	int tmp = m ^ n;
//	int count = 0;
//	while (tmp)
//	{
//		tmp = tmp & (tmp - 1);
//		count++;
//	}
//	return count;
//}
//int main()
//{
//	int m, n;
//	while (scanf("%d %d", &m, &n) == 2)
//	{
//		printf("%d\n", calc_diff_bit(m, n));
//	}
//	return 0;
//}

//打印整数二进制的奇数位和偶数位
//获取一个整数二进制序列中所有的偶数位和奇数位，分别打印出二进制序列

/*
思路：
1. 提取所有的奇数位，如果该位是1，输出1，是0则输出0
2. 以同样的方式提取偶数位置

检测num中某一位是0还是1的方式：
1. 将num向右移动i位
2. 将移完位之后的结果与1按位与，如果：
结果是0，则第i个比特位是0
结果是非0，则第i个比特位是1
*/

//void Printbit(int num)
//{
//	for (int i = 31; i >= 1; i -= 2)
//	{
//		printf("%d ", (num >> i) & 1);
//	}
//	printf("\n");
//
//	for (int i = 30; i >= 0; i -= 2)
//	{
//		printf("%d ", (num >> i) & 1);
//	}
//	printf("\n");
//}
//int main()
//{
//	int num = 0;
//	printf("请输入一个数： ");
//	scanf("%d", &num);
//	Printbit(num);
//	return 0;
//}
//统计二进制中1的个数
//#include<stdio.h>
////Hamming_weight算法二---只考虑1的位数
//int Hamming_weight_2(int number)
//{
//    int count_ = 0; //声明计数变量
//
//    while (number != 0)  //遍历
//    {
//        number &= number - 1;
//        count_++;
//    }
//    return count_;
//}
//
//int main()
//{
//    int n;
//    while (scanf("%d", &n) != EOF)  //读入整数和打印1的个数
//    {
//        printf("%d \n", Hamming_weight_2(n));
//    }
//    return 0;
//}

/*
方法一：
思路：
循环进行以下操作，直到n被缩减为0：
   1. 用该数据模2，检测其是否能够被2整除
   2. 可以：则该数据对应二进制比特位的最低位一定是0，否则是1，如果是1给计数加1
   3. 如果n不等于0时，继续1
*/
//int count_one_bit(int n)
//{
//	int count = 0;
//	while (n)
//	{
//		if (n % 2 == 1)
//			count++;
//		n = n / 2;
//	}
//	return count;
//}


/*
上述方法缺陷：进行了大量的取模以及除法运算，取模和除法运算的效率本来就比较低。
方法二思路：
一个int类型的数据，对应的二进制一共有32个比特位，可以采用位运算的方式一位一位的检测，具体如下
*/
//int count_one_bit(unsigned int n)
//{
//	int count = 0;
//	int i = 0;
//	for (i = 0; i < 32; i++)
//	{
//		if (((n >> i) & 1) == 1)
//			count++;
//	}
//	return count;
//}


/*
方法二优点：用位操作代替取模和除法运算，效率稍微比较高
  缺陷：不论是什么数据，循环都要执行32次

方法三：
思路：采用相邻的两个数据进行按位与运算
举例：
9999：‭10 0111 0000 1111‬
第一次循环：n=9999   n=n&(n-1)=9999&9998= 9998
第二次循环：n=9998   n=n&(n-1)=9998&9997= 9996
第三次循环：n=9996   n=n&(n-1)=9996&9995= 9992
第四次循环：n=9992   n=n&(n-1)=9992&9991= 9984
第五次循环：n=9984   n=n&(n-1)=9984&9983= 9728
第六次循环：n=9728   n=n&(n-1)=9728&9727= 9216
第七次循环：n=9216   n=n&(n-1)=9216&9215= 8192
第八次循环：n=8192   n=n&(n-1)=8192&8191= 0


可以观察下：此种方式，数据的二进制比特位中有几个1，循环就循环几次，而且中间采用了位运算，处理起来比较高效
*/
//int count_one_bit(int n)
//{
//	int count = 0;
//	while (n)
//	{
//		n = n & (n - 1);
//		count++;
//	}
//	return count;
//}

//#include <stdio.h>
//int main()
//{
//    int arr[] = { 1,2,3,4,5 };
//    short* p = (short*)arr;
//    int i = 0;
//    for (i = 0; i < 4; i++)
//    {
//        *(p + i) = 0;
//    }
//
//    for (i = 0; i < 5; i++)
//    {
//        printf("%d ", arr[i]);
//    }
//    return 0;
//}
//解析：
//arr数组在内存中的存储格式为：
//0x00ECFBF4:  01 00 00 00
//0x00ECFBF8 : 02 00 00 00
//0x00ECFBFC : 03 00 00 00
//0x00ECFC00 : 04 00 00 00
//0x00ECFC04 : 05 00 00 00
//指针p的类型为short * 类型的，
// 因此p每次只能所有两个字节，for循环对数组中内容进行修改时，一次访问的是：
//arr[0]的低两个字节，arr[0]的高两个字节，arr[1]的低两个字节，
//arr[1]的高两个字节，
//故改变之后，数组中内容如下：
//0x00ECFBF4 : 00 00 00 00
//0x00ECFBF8 : 00 00 00 00
//0x00ECFBFC : 03 00 00 00
//0x00ECFC00 : 04 00 00 00
//0x00ECFC04 : 05 00 00 00
//故最后打印：0   0   3   4   5

//下列程序段的输出结果为
//unsigned long pulArray[] = { 6,7,8,9,10 };
//unsigned long* pulPtr;
//pulPtr = pulArray;
//*(pulPtr + 3) += 3;
//printf(“% d, % d\n”, *pulPtr, *(pulPtr + 3));
//unsigned long pulArray[] = { 6,7,8,9,10 };
//unsigned long* pulPtr;
//pulPtr = pulArray; 
//// 数组名代表数组首元素地址，因此pulptr指向的是数组中第一个元素的位置
//*(pulPtr + 3) += 3; 
//// pulptr+3访问的是数组中第三个元素(数组下标从0开始)，故将9改为9+3=12
//printf(“% d, % d\n”, *pulPtr, *(pulPtr + 3)); 
//// 打印第一个和第三个元素，因此：打印6和12

//#include <stdio.h>
//int main()
//{
//    int a = 0x11223344;
//    char* pc = (char*)&a;
//    *pc = 0;
//    printf("%x\n", a);
//    return 0;
//}
//假设，a变量的地址为0x64，则a变量在内存中的模型为：
//0x64 | 44 |
//0x65 | 33 |
//0x66 | 22 |
//0x67 | 11 |
//char* 类型的指针变量pc指向只能指向字符类型的空间，
//如果是非char类型的空间，必须要将该空间的地址强转为char * 类型。
//char* pc = (char*)&a; pc实际指向的是整形变量a的空间，即pc的内容为0x64，即44，
//* pc = 0，即将44位置中内容改为0，修改完成之后，a中内容为：0x11223300

//写一个函数打印arr数组的内容，不使用数组下标，使用指针。
//#include <stdio.h>
//int main()
//{
//    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//    //在这里完成代码
//    // 分析：因为数组中存储的元素类型是int类型的，因此只要给一个int的指针，
//    依次取索引数组中的每个元素即可
//    int* p = arr;  // 数组名代表数组首元素的地址
//    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
//    {
//        printf("%d ", *p);   // *p: 取到p所指向位置的元素
//        ++p;                 // 获取p的下一个位置
//    }
//
//    return 0;
//}

//写一个函数，可以逆序一个字符串的内容
/*
思路：该题比较简单，请参考代码
*/
//void Reverse(char* str)
//{
//    char* left = str;
//    char* right = str + strlen(str) - 1;
//    while (left < right)
//    {
//        char temp = *left;
//        *left = *right;
//        *right = temp;
//        ++left;
//        --right;
//    }
//}
//int main()
//{
//    char str[] = "hello bit";
//    //在这里完成下面函数，参数自己设计，要求：使用指针
//    Reverse(str);
//    return 0;
//}
// 注意：如果是在线OJ时，必须要考虑循环输入，
//因为每个算法可能有多组测试用例进行验证，参考以下main函数写法，
//int main()
//{
//    char str[101] = { 0 };
//    while (gets(str))
//    {
//        Reverse(str);
//        printf("%s\n", str);
//        memset(str, 0, sizeof(str) / sizeof(str[0]));
//    }
//    return 0;
//}


//求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和，其中a是一个数字
//int main()
//{
//	int i;
//	int  sum = 0;
//	int n = 2;
//	int  temp = 0;
//	for (i = 1; i <= 2; i++) 
//	{
//		//找到相对应的算法，类似于找等式的规律，依次用等式描述出来即可
//		sum = sum * 10 + n;
//		temp = temp + sum;
//	}
//	printf("%d\n", temp);
//	system("pause");
//	return 0;
//}

//求出0～100000之间的所有“水仙花数”并输出。
//“水仙花数”是指一个n位数，其各位数字的n次方之和确好等于该数本身，
//如:153＝1 ^ 3＋5 ^ 3＋3 ^ 3，则153是一个“水仙花数”。
//#include <stdio.h>
//#include <math.h>
//int main()
//{
//	int i = 0;
//	for (i = 1; i <= 99999; i++)
//	{
//		int tmp = i;//各位数
//		int count = 0;//n
//		int sum = 0;
//		while (tmp)
//		{
//			tmp /= 10;//各位数
//			count++;
//		}
//		tmp = i;
//		while (tmp)
//		{
//			sum += pow((tmp % 10), count);
//			tmp /= 10;
//		}
//		if (sum == i)
//		{
//			printf("%d是水仙花数\n", i);
//		}
//	}
//	return 0;
//}


//打印菱形
//#include<stdio.h>
//#include<stdlib.h>
//void PrintLine(int blank_count, int start_count) {
//	int i = 0;
//	for (; i < blank_count; i++) {
//		printf(" ");  //打印空格
//	}
//	for (i = 0; i < start_count; i++) {
//		printf("*");
//	}
//	printf("\n");
//}
//void  PrintLingxing(int n) {
//	//打印上半部分
//	int i = 1;
//	for (i = 1; i < n; i++) {
//		PrintLine(n - i, 2 * i - 1);  // 打印每一行的空格和每一行的星号
//	}
//	//打印中间部分
//	PrintLine(0, 2 * n - 1);
//	//打印下半部分
//	for (i = n - 1; i > 0; i--) {
//		PrintLine(n - i, 2 * i - 1);
//	}
//}
//int main() {
//	PrintLingxing(7);    //对半的行数
//	system("pause");
//	return 0;
//}




